<!--
 * @Author: Sammer.Sun Sammer.Sun@gaiaworks.cn
 * @Date: 2023-04-13 09:14:05
 * @LastEditors: Sammer.Sun Sammer.Sun@gaiaworks.cn
 * @LastEditTime: 2023-05-24 09:41:35
-->
<template>
  <!--  search bar 目前只支持 输入框和下拉框  date dateRange  -->
  <section
    v-loading="props.loading && loading"
    element-loading-text="拼命加载中"
    class="p10"
  >
    <header>
      <ul class="list-group df fww rg10 cg10">
        <!-- 搜索栏 start -->
        <li class="df aic" :key="item.key" v-for="(item, i) in props.searchInfo">
          <span
            :style="{ width: state.width }"
            class="fs12 mr4 dib custom-search-label tar"
            >{{ item.label }}</span
          >
          <el-select
            :size="size"
            filterable
            v-model="state.params[item.key]"
            v-if="item.type === 'select'"
            placeholder="请选择"
            style="width: 200px;"
            :collapse-tags="!!item.collapseTags"
            :collapse-tags-tooltip="!!item.collapseTagsTooltip"
            :multiple="item.multiple || false"
            @change="
              () => {
                changeSearch(item);
              }
            "
            clearable
          >
            <el-option
              :label="opt.label"
              :value="opt.value"
              :key="index"
              v-for="(opt,index) in (item.options || [])"
            >
            </el-option>
          </el-select>
          <el-input
            v-model.trim="state.params[item.key]"
            :size="size"
            style="width: 200px;"
            @input="
              () => {
                changeSearch(item);
              }
            "
            clearable
            v-if="item.type === 'input' || !item.type"
            placeholder="请输入"
          ></el-input>
          <el-input
            v-model.trim="state.params[item.key]"
            :size="size"
            style="width: 200px;"
            :step="item.step || 1"
            :min="item.min || 1"
            :max="item.max || 1000000000000"
            type="number"
            @input="
              () => {
                changeSearch(item);
              }
            "
            clearable
            v-if="item.type === 'inputNumber' "
            placeholder="请输入"
          ></el-input>
          <!-- 增加 switch 组件 start-->
          <el-switch
            v-model="state.params[item.key]"
            :size="size"
            :active-value=' typeof item.activeValue  === "number" ?  item.activeValue  :  (item.activeValue || false)'
            :inactive-value=' typeof item.inActiveValue  === "number" ?  item.inActiveValue  :  (item.inActiveValue || false)'
            @change="
              () => {
                changeSearch(item);
              }
            "
            v-if="item.type === 'switch'"
          ></el-switch>
          <!-- 增加 switch 组件 end -->

          <el-date-picker
            v-if="item.type === 'dateRange'"
            :size="size"
            class="time-pick-active"
            @change="(e) => changeTime(e, i,item)"
            value-format="YYYY-MM-DD"
            type="daterange"
            style="width: 200px; font-size: 12px;"
            range-separator="~"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            v-model="state[i]"
          ></el-date-picker>
          <el-date-picker
            value-format="YYYY-MM-DD"
            v-if="item.type === 'date'"
            style="width: 200px;"
            @change="
              () => {
                changeSearch(item);
              }
            "
            v-model="state.params[item.key]"
            placeholder="请选择"
            :size="size"
          />
          <div   v-if="item.type === 'slot'">
            <slot :name="item.key"></slot>
          </div>

        </li>
        <li class="ml-auto df aic">
          <slot :scope="state" name="searchPre"></slot>
          <el-button type="primary" @click="fetchData" :size="size"
            >搜索</el-button
          >
          <el-button @click="reset" size="small">重置</el-button>
          <slot :scope="state" name="searchAfter"></slot>
          <!-- 过滤条件设置 -->
          <setTable
          v-if='props.setTableColumn'
            class="ml10"
            @change="changeColumns"
            :columns="props.columns"
          ></setTable>
        </li>
        <!-- 搜索栏 start -->
      </ul>
    </header>
    <div>
      <!-- 默认插槽 介于搜索栏和table 之间 -->
      <slot></slot>
    </div>
    <div>
      <!-- table 都支持 插槽 -->
      <el-table
        :size="size"
        sortable='custom'
        :border="props.border"
         @selection-change="handleSelectionChange"
        :height="tableHeight.height"
        @sort-change="handleSortChange"
        v-resizeHeight="{ tableHeight }"
        :data="state.data"
        ref="tableRef"
      >
       <el-table-column v-if="props.selection"  align="center" type="selection" width="55" />
        <el-table-column
          :key="item.prop"
          v-for="item in columns"
          :prop="item.prop"
          :sortable="!!item.sortable"
          :label="item.label"
          :fixed="item.fixed || null"
          :show-overflow-tooltip="!!item.showOverflow"
          :min-width="item.minWidth || 'auto'"
          :width="
            item.minWidth
              ? 'auto'
              : item.width ||
                item.label.length * 16 + (!!item.sortable ? 50 : 20) ||
                'auto'
          "
          :align="item.align || 'center'"
        >
          <template #default="{row,$index}">
            <slot :scope="{ ...row, $index }" :index='$index' :data="row" :name="item.prop">
              <div :name="$index">{{ row[item.prop] }}</div>
            </slot>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-if="props.showPagination"
        :size="size"
        :total="total"
        v-model:page="params.pageNum"
        v-model:limit="params.pageSize"
        @pagination="
          () => {
            fetchData();
          }
        "
      />
    </div>
  </section>
</template>
<script setup>
import { reactive, onMounted, toRef, toRefs } from 'vue';
import { fetchTableList } from '@/api/menu';
import setTable from './setTable.vue';
const loading = ref(false);
const size = ref('small');
let timer = null;
const dateTypeIsArray = ['dateRange']; // 数组类型数据
const emit = defineEmits(['reset','handleSelectionChange'])
const isFunction = (fn) =>
  Object.prototype.toString.call(fn).includes('Function');
const isArray = (fn) => Object.prototype.toString.call(fn).includes('Array');
const props = defineProps({
  /**
   * @property
   * 搜索栏信息
   *  时间区间传startValue  endValue  defaultValue 传空数组
   */
  searchInfo: {
    type: Array,
    default: () => []
  },
  loading: {
    type: Boolean,
    default: false
  },
   selection: {
    type: Boolean,
    default: false
  },
  keepAlive: {
    type: Boolean, // 是否缓存
    default: false
  },
  params: {
    type: Object,
    default: () => {}
  },
  setTableColumn:{ // 设置行字的toggle
      type: Boolean,
    default: true
  },
  columns: {
    type: Array,
    default: () => []
  },
  methods: {
    type: String,
    default: 'get'
  },
  maxHeight:{
     type: Number,
    default: 0
  },
  border: {
    // table 边框
    type: Boolean,
    default: true
  },
  url: {
    //  列表请求接口列表
    type: String,
    default: '',
    required: true
  },
  fn: {
    //  列表数据处理函数
    type: Function,
    default: (val) => {}
  },
  showPagination: {
    //  是否展示分页
    type: Boolean,
    default: true
  }
});
/**  搜索栏事件查询 */
const changeSearch = (prop) => {
  if (prop.event) {
    const t =  (prop.type === 'input' || !prop.type) ? 300 : 40
    if (timer) {
      window.clearInterval(timer);
    }
    timer = window.setTimeout(() => {
      fetchData();
    },t);
  }
};
const columns = ref([...props.columns]);
const changeColumns = (val) => {
  columns.value = val;
};
requestAnimationFrame(() => {
  changeColumns(
    (() => {
      const current = localStorage.getItem(window.location.hash);
      if (current) {
        const filterData = JSON.parse(current);
        const data = props.columns.filter((item) =>
          filterData.includes(item.name || item.text || item.label)
        );
        return data;
      } else {
        return props.columns;
      }
    })()
  );
});
const tableRef = ref();
const tableHeight = reactive({
  height: 600,
  maxHeight:props.maxHeight
});
const changeTime = (e, i,item) => {
  if (e) {
    state.params[props.searchInfo[i].keys[0]] = e[0];
    state.params[props.searchInfo[i].keys[1]] = e[1];
  } else {
    state.params[props.searchInfo[i].keys[0]] = null;
    state.params[props.searchInfo[i].keys[1]] = null;
  }
  changeSearch(item)
};
const state = reactive({
  data: [],
  total: 0,
  width: 'auto',
  params: { pageNum: 1, pageSize: 10 }
});
let sortParams = {}; // 排序参数
const handleSelectionChange = (v)=>{
  console.log(v)
  emit('handleSelectionChange',v);
}
const reset = () => {
  emit('reset');
  setTimeout(()=>{

  sortParams = {};
  tableRef.value.clearSort();
  props.searchInfo.forEach((item, i) => {
    //  初始化搜索栏信息
    if (!dateTypeIsArray.includes(item.type)) {
      state.params[item.key] = item.defaultValue || null;
    } else {
      if (isArray(item.keys)) {
        state[i] = [];
        item.keys.forEach((_, i) => {
          state.params[_] = item.defaultValues ? item.defaultValues[i] : null;
        });
      }
    }
  });
  fetchData();
  })

};
const setLabelWidth = () => {
  /** 搜索栏 宽度设置 */
  const span = Array.from(
    document.querySelectorAll('.custom-search-label')
  ).map((_) => _.offsetWidth);
  state.width = Math.max(...span) + 'px';
};
const handleSortChange = (v) => {
  sortParams.column = v.prop;
  sortParams.sort = v.order
    ? v.order === 'descending'
      ? 'desc'
      : 'asc'
    : null;
  fetchData();
};

const fetchData = () => {
  /**
   * 数据处理 start
   */
  const query = { ...props.params, ...state.params };
  Object.keys(query).forEach((_) => {
    if (query[_] === undefined) {
      delete query[_];
    }
  });
  /**
   * 数据处理 end 小程序用canvas 绘制折线图
   */
  const loadTime = Date.now();
  loading.value = true;
  const pageInfo = 'pageNum='+state.params.pageNum+'&pageSize='+state.params.pageSize;
  const url = props.methods === 'get' ? props.url : props.url + '?' + pageInfo
  console.log(query)
  props.searchInfo.forEach((item, i) => {
    if(item.translate &&  item.key in query ){
      item.translate(query,item.key) // 数据转化 
    }
  })
  fetchTableList(url, { ...sortParams, ...query }, props.methods)
    .then((res) => {
      if (isFunction(props.fn)) {
        props.fn(res);
      }
      state.data = res.rows || res.data || [];
      state.total = res.total || 0;
    })
    .finally((e) => {
      const t = Date.now();
      if (t - loadTime > 150) {
        setTimeout(() => {
          loading.value = false;

        }, 200);
      } else {
        loading.value = false;
      }
    }); 
};
defineExpose({
  fetchData,
  reset,
  state
});
onMounted(() => {
  setLabelWidth(); /*设置搜索栏文本信息宽度*/
 !props.keepAlive  && reset(); //  请求列表数据
});
const { total, params } = toRefs(state);
</script>
